﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web;

namespace ASPNETPerformance.App_BusinessLogic.Helpers {
    public static class CookieHelper {

        public static string GetCookieValue( string cookieName, bool decode ) {
            return GetCookieValue( cookieName, decode, null );
        }

        public static string GetCookieValue( string cookieName, bool decode, bool? compressedCookie ) {
            if( HttpContext.Current.Request.Cookies[ cookieName ] == null ) {
                return string.Empty;
            }

            try {
                string tmp = HttpContext.Current.Request.Cookies[ cookieName ].Value.ToString();
                if( decode )
                    tmp = HttpContext.Current.Server.UrlDecode( tmp );

                if( compressedCookie.HasValue ) {
                    byte[] bytCook = Convert.FromBase64String( tmp );
                    MemoryStream inMs = new MemoryStream( bytCook );
                    inMs.Seek( 0, 0 );
                    DeflateStream zipStream = new DeflateStream( inMs, CompressionMode.Decompress, true );
                    byte[] outByt = ReadFullStream( zipStream );
                    zipStream.Flush();
                    zipStream.Close();
                    MemoryStream outMs = new MemoryStream( outByt );
                    outMs.Seek( 0, 0 );
                    BinaryFormatter bf = new BinaryFormatter();
                    tmp = ( string )bf.Deserialize( outMs, null );
                }

                return tmp;
            }
            catch {
                return string.Empty;
            }
        }

        public static void SetCookie( string cookieName, string value, TimeSpan? ts ) {
            SetCookie( cookieName, value, ts, null );
        }

        public static void SetCookie( string cookieName, string value, TimeSpan? ts, bool? compressedCookie ) {
            value = HttpContext.Current.Server.UrlEncode( value );

            if( compressedCookie.HasValue ) {
                try {
                    BinaryFormatter bf = new BinaryFormatter();
                    MemoryStream ms = new MemoryStream();
                    bf.Serialize( ms, value );
                    byte[] inbyt = ms.ToArray();
                    MemoryStream objStream = new MemoryStream();
                    DeflateStream objZS = new DeflateStream( objStream, CompressionMode.Compress );
                    objZS.Write( inbyt, 0, inbyt.Length );
                    objZS.Flush();
                    objZS.Close();
                    byte[] b = objStream.ToArray();
                    string sCookieVal = Convert.ToBase64String( b );
                    value = sCookieVal;
                }
                catch( Exception ex ) {
                    throw ex;
                }
            }

            HttpCookie Cookie = new HttpCookie( cookieName, value );
            if( ts.HasValue ) {
                DateTime dt = DateTime.Now;
                Cookie.Expires = dt.Add( ts.Value );
            }
            HttpContext.Current.Response.Cookies.Add( Cookie );
        }

        public static void DeleteCookie( string cookieName ) {
            HttpCookie Cookie = HttpContext.Current.Request.Cookies[ cookieName ];
            if( Cookie != null ) {
                Cookie.Expires = DateTime.Now.AddDays( -2 );
                HttpContext.Current.Response.Cookies.Add( Cookie );
            }
        }

        public static bool CookieExists( string cookieName ) {
            bool exists = false;
            HttpCookie cookie = HttpContext.Current.Request.Cookies[ cookieName ];
            if( cookie != null )
                exists = true;
            return exists;
        }

        public static Dictionary<string, string> GetAllCookies() {
            Dictionary<string, string> cookies = new Dictionary<string, string>();
            foreach( string key in HttpContext.Current.Request.Cookies.AllKeys ) {
                cookies.Add( key, HttpContext.Current.Request.Cookies[ key ].Value );
            }
            return cookies;
        }

        public static void DeleteAllCookies() {
            var x = HttpContext.Current.Request.Cookies;
            foreach( HttpCookie cook in x ) {
                DeleteCookie( cook.Name );
            }
        }

        private static byte[] ReadFullStream( Stream stream ) {
            byte[] buffer = new byte[ 32768 ];
            using( MemoryStream ms = new MemoryStream() ) {
                while( true ) {
                    int read = stream.Read( buffer, 0, buffer.Length );
                    if( read <= 0 )
                        return ms.ToArray();
                    ms.Write( buffer, 0, read );
                }
            }
        }
    }
}